package com.seeTools.next.service.sys.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.seeTools.next.api.bo.sys.LoginRequest;
import com.seeTools.next.api.bo.wx.WechatLoginRequest;
import com.seeTools.next.api.bo.wx.WechatSessionResponse;
import com.seeTools.next.api.entity.sys.SysRole;
import com.seeTools.next.api.entity.sys.SysTenant;
import com.seeTools.next.api.entity.sys.SysUser;
import com.seeTools.next.common.core.ServiceException;
import com.seeTools.next.conf.ThreadLocalHolder;
import com.seeTools.next.service.sys.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 系统登录 服务实现类
 *
 * @author xiaotong
 */
@Slf4j
@Service
public class SysLoginServiceImpl implements ISysLoginService {

    @Resource
    private ISysUserService iSysUserService;

    @Resource
    private ISysRoleService iSysRoleService;

    @Resource
    private ISysMenuService iSysMenuService;

    @Resource
    private ISysTenantService iSysTenantService;

    @Value("${wechat.appId}")
    private String appId;

    @Value("${wechat.appSecret}")
    private String appSecret;

    @Override
    public SysUser login(LoginRequest loginRequest, String type) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysUser::getLoginName, loginRequest.getLoginName())
                .eq(SysUser::getPassword, loginRequest.getPassword());
        List<SysUser> userList = iSysUserService.list(queryWrapper);
        if (!userList.isEmpty()) {
            SysUser user = userList.get(0);
            if (user.getExpirationDate() != null && !user.getExpirationDate().isAfter(LocalDateTime.now())) {
                throw new ServiceException("该账户的有效截止日已到期，请联系管理员！");
            }
            if (user.getActive() == 0) {
                throw new ServiceException("该账户处于禁用状态，请联系管理员！");
            }
            Long tenantId = user.getTenantId();
            Long userId = user.getId();
            String device = user.getLoginName() + type;
            StpUtil.login(userId, device);
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            user.setTokenName(tokenInfo.getTokenName());
            user.setTokenValue(tokenInfo.getTokenValue());
            ThreadLocalHolder.setTenantId(tenantId);
            StpUtil.getSession().set("tenantId", tenantId);
            // 刷新最近登录时间
            iSysUserService.updateLastLoginTime(userId, device);
            return user;
        }
        return null;
    }


    /**
     * 微信登录
     *
     * @param request
     * @param type
     * @return
     */
    @Override
    public SysUser wechatLogin(WechatLoginRequest request, String type) {
        // 构建请求URL
        String url = "https://api.weixin.qq.com/sns/jscode2session" +
                "?appid=" + appId +
                "&secret=" + appSecret +
                "&js_code=" + request.getCode() +
                "&grant_type=authorization_code";

        // 发送请求到微信API
        HttpResponse response  = HttpRequest.get(url).execute();
        if (response.isOk()) {
            String body = response.body();
            WechatSessionResponse sessionResponse  = JSON.parseObject(body, WechatSessionResponse.class);
            if (sessionResponse != null && sessionResponse.getOpenid() != null) {
                // 根据openid查找或创建用户
                return findOrCreateUser(sessionResponse.getOpenid(), request.getSysUser());
            }
        }
        return null;
    }


    /**
     * 查找或创建用户
     *
     * @param openid
     * @param sysUser
     * @return
     */
    public SysUser findOrCreateUser(String openid, SysUser sysUser) {
        if (StrUtil.isNotEmpty(openid)) {
            SysUser user = iSysUserService.findOne(SysUser::getWxOpenid, openid);
            if (ObjectUtil.isNotEmpty(user)) {
                iSysUserService.save(sysUser);
            }
            return user;
        }
        return null;
    }

    @Override
    public void logout() {
        long userId = getLoginUserId();
        log.info("@logout#id={}", userId);
        StpUtil.logout();
    }

    @Override
    public SysUser getUserInfo() {
        long userId = getLoginUserId();
        SysUser user = iSysUserService.getById(userId);
        List<SysRole> roleList = iSysRoleService.getRoleListByUserId(userId);
        user.setRoles(roleList);
        List<String> authBtnList = iSysMenuService.getUserAuthBtnList(userId);
        user.setAuthBtnList(authBtnList);
        SysTenant tenant = iSysTenantService.findByTenantIdCache(user.getTenantId());
        user.setTenantName(tenant != null ? tenant.getTenantName() : "");
        return user;
    }

    @Override
    public Long getLoginTenantId() {
        return ThreadLocalHolder.getTenantId();
    }

    @Override
    public Long getLoginUserId() {
        return StpUtil.getLoginIdAsLong();
    }
}
